package data

import (
	"context"
	"strconv"

	"github.com/go-kratos/kratos/v2/log"
	goRedis "github.com/redis/go-redis/v9"

	"gitee.com/danqingzhao/go-dango/apps/user/biz"
	"gitee.com/danqingzhao/go-dango/pkg/proto/settings"
	"gitee.com/danqingzhao/go-dango/pkg/third/orm"
	"gitee.com/danqingzhao/go-dango/pkg/third/redis"
)

type recordRepo struct {
	data *Data
	log  *log.Helper
}

func NewRecordRepo(data *Data, logHelpers *settings.LogHelpers) biz.RecordRepo {
	return &recordRepo{data: data, log: logHelpers.Data}
}

func (r *recordRepo) CreateModel(ctx context.Context, m *biz.LoginRecordModel) error {
	if err := orm.DBCreate(ctx, r.data.gormDB, &biz.LoginRecordModel{}, m); err != nil {
		r.log.WithContext(ctx).Error(err.Error())
		return err
	}
	return nil
}

func (r *recordRepo) ListModel(
	ctx context.Context,
	qp orm.QueryParams,
) (int64, []biz.LoginRecordModel, error) {
	var ms []biz.LoginRecordModel
	count, err := orm.DBList(ctx, r.data.gormDB, &biz.LoginRecordModel{}, &ms, qp)
	if err != nil {
		r.log.WithContext(ctx).Error(err.Error())
		return 0, nil, err
	}
	return count, ms, nil
}

func (r *recordRepo) GenerateLoginNumKey(username string) string {
	return "login_num_" + username
}

func (r *recordRepo) GetRemainLoginNum(ctx context.Context, username string) (uint32, error) {
	loginNumKey := r.GenerateLoginNumKey(username)
	num, err := redis.RedisGet(r.data.redisCli, redis.DefaultTimeOut, loginNumKey)
	if err != nil {
		if err == goRedis.Nil {
			return LoginFailMaxTimes - 1, nil
		}
		r.log.WithContext(ctx).Error(err.Error())
		return 0, err
	}
	if num != "" {
		n, pErr := strconv.ParseInt(num, 10, 64)
		if pErr != nil {
			r.log.WithContext(ctx).Error(pErr.Error())
			return 0, pErr
		}
		return uint32(n - 1), nil
	}
	return LoginFailMaxTimes - 1, nil
}

func (r *recordRepo) SetRemainLoginNum(ctx context.Context, username string, num uint32) error {
	loginNumKey := r.GenerateLoginNumKey(username)
	if err := redis.RedisSet(r.data.redisCli, redis.DefaultTimeOut, loginNumKey, num, LoginFailLockMinutes); err != nil {
		r.log.WithContext(ctx).Error(err.Error())
		return err
	}
	return nil
}
